<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use framework\libraries\Controller;
use framework\libraries\ErrorType;
use framework\libraries\Stdio;
use framework\support\Db;
use framework\support\Redis;
use framework\libraries\Utils;
use Respect\Validation\Validator as v;
use Gregwar\Captcha\CaptchaBuilder;

class auth extends Controller
{
    function admin_login_post()
    {
        $captchaRequired = $_ENV["CAPTCHA_REQUIRED"] ?? false;

        if ($captchaRequired === true) {
            try {
                $data = v::input($this->post(), [
                    'username' => v::alnum()->length(5, 64)->setName('用户名'),
                    'password' => v::length(5, 64)->setName('密码'),
                    'token' => v::length(32)->setName('图形 token '),
                    'code' => v::alnum()->length(4, 10)->setName('图形验证码'),
                ]);
            } catch (Exception $e) {
                return $this->Error(ErrorType::FORM_VALIDATE_FAIL, $e->getMessage());
            }
            try {
                $key = $_ENV["CAPTCHA_SECRET_KEY"] ?? 'WeeSpeed@captcha';
                $jwtData = JWT::decode($data['token'], new Key($key, 'HS256'));

                if ($jwtData->expire < time()) {
                    return $this->Error(ErrorType::CAPTCHA_EXPIRED);
                }

                if (
                    $jwtData->code != Utils::EncodeCaptcha($jwtData->expire, $data['code']) &&
                    !($_ENV["APP_DEBUG"]  && $data['code'] == '19527')
                ) {
                    return $this->Error(ErrorType::CAPTCHA_ERROR);
                }
            } catch (\Exception $e) {
                return $this->Error(ErrorType::CAPTCHA_ERROR);
            }
        } else {
            try {
                $data = v::input($this->post(), [
                    'username' => v::alnum()->length(5, 64)->setName('用户名'),
                    'password' => v::length(5, 64)->setName('密码')
                ]);
            } catch (Exception $e) {
                return $this->Error(ErrorType::FORM_VALIDATE_FAIL, $e->getMessage());
            }
        }

        $lockKey = "loginAdminFail_{$data['username']}";
        $failCount = intval(Redis::get($lockKey) ?? 0);
        if ($failCount > 5) {
            return $this->Error(ErrorType::CUSTOM_MSG, "密码错误次数过多，账号已被锁定");
        }


        $admin = Db::get("admin", "*", [
            'username' => $data['username'],
            'is_delete' => 0
        ]);

        if (!$admin) {
            return $this->Error(ErrorType::NOT_EXISTS, $data['username']);
        }

        $encodePassword = Utils::EncodeAdminPassword($data['username'], $data['password']);
        if ($admin['password'] != $encodePassword) {
            $failCount++;
            Redis::setEx($lockKey, 86400, $failCount);

            return $this->Error(ErrorType::PASSWORD_MISMATCH, $encodePassword);
        }

        if ($admin['is_banned']) {
            return $this->Error(ErrorType::ACCOUNT_DISABLED);
        }

        $time = strtotime('+1 days');
        $payload = array(
            "aid" => $admin['id'],
            "expire" => $time
        );

        $jwt = JWT::encode($payload, $_ENV['ADMIN_SECRET_KEY'] ?? 'WeeSpeed@admin', 'HS256');
        Redis::del($lockKey);

        return $this->Success([
            "token" => $jwt,
            "expire" => $time,
            "info" => Utils::cleanArray((array)$admin, [
                'password',
                'is_banned',
                'is_delete',
                'update_time'
            ]),
        ]);
    }

    function captcha_get()
    {
        $code = Utils::randomString('numeric', 5);
        $captcha = new CaptchaBuilder($code);
        $captcha->build(80, 30);
        $image = $captcha->get();
        $time = strtotime('+180 seconds');
        if (getenv("APP_DEBUG")) {
            $time = strtotime('+30 days');
        }
        $payload = array(
            "code" => Utils::EncodeCaptcha($time, $code),
            "expire" => $time
        );
        $base64 = "data:image/jpeg;base64," . base64_encode($image);
        $key = $_ENV["CAPTCHA_SECRET_KEY"] ?? 'WeeSpeed@captcha';
        $jwt = JWT::encode($payload, $key, 'HS256');
        return $this->Success([
            "token" => $jwt,
            "image" => $base64,
            "expire" => $time,
        ]);
    }
}
